package com.ruoyi.gateway.config;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springdoc.core.models.GroupedOpenApi;
import org.springdoc.core.properties.AbstractSwaggerUiConfigProperties;

/**
 * 聚合系统接口
 *     springdoc:
 *        swagger-ui:
 *          urls:
 *            - name: default
 *              url: /v3/api-docs
 *          path: /swagger-ui.html
 * @author ruoyi
 */
@Component
public class SwaggerProvider implements WebFluxConfigurer {

    /**
     * OpenAPI 默认的url后缀
     */
    public static final String OPENAPI_URL = "/v3/api-docs";

    /**
     * 网关路由
     */
    @Lazy
    @Autowired
    private RouteLocator routeLocator;

    @Autowired
    private GatewayProperties gatewayProperties;

    @Autowired(required = false)
    private SwaggerUiConfigProperties swaggerUiConfigProperties;

    /**
     * 获取所有服务的 API 文档分组
     */
    public List<GroupedOpenApi> getApiGroups() {
        List<String> routes = new ArrayList<>();
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));

        return gatewayProperties.getRoutes().stream()
                .filter(routeDefinition -> routes.contains(routeDefinition.getId()))
                .filter(routeDefinition -> !"ruoyi-auth".equalsIgnoreCase(routeDefinition.getId()))
                .flatMap(routeDefinition -> routeDefinition.getPredicates().stream()
                        .filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName()))
                        .map(predicateDefinition -> {
                            String name = routeDefinition.getId();
                            String path = predicateDefinition.getArgs()
                                    .get(NameUtils.GENERATED_NAME_PREFIX + "0")
                                    .replace("/**", OPENAPI_URL);

                            // 配置Swagger UI URLs
                            if (swaggerUiConfigProperties != null) {
                                AbstractSwaggerUiConfigProperties.SwaggerUrl swaggerUrl =
                                        new AbstractSwaggerUiConfigProperties.SwaggerUrl(name, path, name);
                                swaggerUiConfigProperties.getUrls().add(swaggerUrl);
                            }

                            return GroupedOpenApi.builder()
                                    .group(name)
                                    .pathsToMatch("/" + name + "/**")
                                    .build();
                        }))
                .collect(Collectors.toList());
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // SpringDoc UI 资源路径
        registry.addResourceHandler("/swagger-ui/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/springdoc-openapi-ui/")
                .resourceChain(false);
    }
}